
"""
Copyright 2009 Andrew T. Barker

This file is part of Second Budget.

Second Budget is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Second Budget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Second Budget, in the file LICENSE.  If not, see 
<http://www.gnu.org/licenses/>.
"""

import datetime,os
import sbconfig
from datetime import date,time

try:
    from pylab import *
    usepylab = True
except ImportError:
    usepylab = False

sbc = sbconfig.SBConfig()

logfile = sbc.logfile
stampfmt = sbc.stampfmt

class LogData:

    def __init__(self,file = logfile):
        if os.path.exists(logfile):
            fd = open(logfile,"r")
            self.stampscores = {}
            for line in fd:
                parsed = line.split(",")
                self.stampscores[datetime.datetime.strptime(parsed[0],stampfmt)] = int(parsed[1])
            fd.close()
        else:
            self.stampscores = {datetime.datetime.fromordinal(1):0}

    def getlaststamp(self):
        laststamp = datetime.datetime.fromordinal(1)
        for stamp in self.stampscores.keys():
            if stamp > laststamp:
                laststamp = stamp
        return laststamp

class ScoreTracker:

    def __init__(self):
        self.items = 0
        self.total = 0

    def update(self,score):
        if score == 1: self.total = self.total + 1
        if not score == 0: self.items = self.items + 1

    def score(self):
        if self.items > 0:
            return float(self.total)/float(self.items)
        else:
            return 0.0
    

def main():
    ld = LogData()

    # last stamp
    laststamp = datetime.datetime.fromordinal(1)
    for stamp in ld.stampscores.keys():
        if stamp > laststamp:
            laststamp = stamp
    print "last stamp:",str(laststamp)

    # total score
    s = ScoreTracker()
    for j in ld.stampscores.values():
        s.update(j)
    print "total score:",s.score()

    # morning score
    s = ScoreTracker()
    for stamp in ld.stampscores.keys():
        if stamp.hour < 12:
            s.update(ld.stampscores[stamp])
    print "morning score:",s.score()

    # weekdays
    print "\nWeekday breakdown:"
    scores = []
    for j in range(7):
        scores.append(ScoreTracker())
    for stamp in ld.stampscores.keys():
        for k in range(7):
            if stamp.weekday() == k:
                scores[k].update(ld.stampscores[stamp])
    for j in range(7):
        print "score on day",j,":",scores[j].score(),"("+str(scores[j].items)+")"

    # over time of day
    print "\nTime breakdown:"
    bins = [time(7), time(9), time(10), time(11), time(12), time(13), time(14),time(15), time(16), time(17), time(19)]
    scores = []
    for j in range(len(bins)-1):
        scores.append(ScoreTracker())
    for stamp in ld.stampscores.keys():
        for k in range(len(bins)-1):
            if stamp.time() > bins[k] and stamp.time() < bins[k+1]:
                scores[k].update(ld.stampscores[stamp])
    for j in range(len(bins)-1):
        print "score between",bins[j],"and",bins[j+1],":",scores[j].score(),"("+str(scores[j].items)+")"
        
    # over longer term
    print "\nOver last ten weeks:"
    oneweek = datetime.timedelta(7)
    bins = []
    for j in range(11):
        bins.append(laststamp - (10-j)*oneweek)
    scores = []
    for j in range(len(bins)-1):
        scores.append(ScoreTracker())
    for stamp in ld.stampscores.keys():
        for k in range(len(bins)-1):
            if stamp >= bins[k] and stamp < bins[k+1]:
                scores[k].update(ld.stampscores[stamp])
    for j in range(len(bins)-1):
        print "score between",bins[j],"and",bins[j+1],":",scores[j].score(),"("+str(scores[j].items)+")"
    if usepylab:
        figure(2)
        x = []
        xstrs = []
        y = []
        for j in range(len(bins)-1):
            x.append(j)
            xstrs.append(str(bins[j]))
            y.append(scores[j].score())
        plot(x,y)
        title("Over last ten weeks")
        xticks(x,xstrs)

    # last ten days
    print "\nOver last ten days:"
    oneday = datetime.timedelta(1)
    bins = []
    for j in range(11):
        bins.append(laststamp - (10-j)*oneday)
    scores = []
    for j in range(len(bins)-1):
        scores.append(ScoreTracker())
    for stamp in ld.stampscores.keys():
        for k in range(len(bins)-1):
            if stamp >= bins[k] and stamp < bins[k+1]:
                scores[k].update(ld.stampscores[stamp])
    for j in range(len(bins)-1):
        print "score between",bins[j],"and",bins[j+1],":",scores[j].score(),"("+str(scores[j].items)+")"
    if usepylab:
        figure(1)
        x = []
        xstrs = []
        y = []
        for j in range(len(bins)-1):
            x.append(j)
            xstrs.append(str(bins[j]))
            y.append(scores[j].score())
        plot(x,y)
        title("Over last ten days")
        xticks(x,xstrs)
    
    if usepylab:
        show()

if __name__ == "__main__":
    main()
